package requestmgr

import (
	imageCVEDataStore "github.com/stackrox/rox/central/cve/image/v2/datastore"
	deploymentDataStore "github.com/stackrox/rox/central/deployment/datastore"
	imageDataStore "github.com/stackrox/rox/central/image/datastore"
	imageV2Datastore "github.com/stackrox/rox/central/imagev2/datastore"
	"github.com/stackrox/rox/central/reprocessor"
	"github.com/stackrox/rox/central/sensor/service/connection"
	views "github.com/stackrox/rox/central/views/imagecve"
	"github.com/stackrox/rox/central/vulnmgmt/vulnerabilityrequest/cache"
	vulnReqDataStore "github.com/stackrox/rox/central/vulnmgmt/vulnerabilityrequest/datastore"
	"github.com/stackrox/rox/pkg/concurrency"
	"github.com/stackrox/rox/pkg/env"
	"github.com/stackrox/rox/pkg/logging"
	"github.com/stackrox/rox/pkg/sync"
	"golang.org/x/sync/semaphore"
)

var (
	once     sync.Once
	instance Manager

	log = logging.LoggerForModule()
)

func initialize() {
	instance = New(
		deploymentDataStore.Singleton(),
		vulnReqDataStore.Singleton(),
		cache.PendingReqsCacheSingleton(),
		cache.ActiveReqsCacheSingleton(),
		imageDataStore.Singleton(),
		imageV2Datastore.Singleton(),
		imageCVEDataStore.Singleton(),
		connection.ManagerSingleton(),
		reprocessor.Singleton(),
		views.Singleton(),
	)
}

// Singleton provides the instance of Manager to use.
func Singleton() Manager {
	once.Do(initialize)
	return instance
}

// New returns an initialized manager, and starts the manager's processing loop in the background.
func New(
	deployments deploymentDataStore.DataStore,
	vulnReqs vulnReqDataStore.DataStore,
	pendingVulnReqsCache cache.VulnReqCache,
	activeVulnReqsCache cache.VulnReqCache,
	images imageDataStore.DataStore,
	imagesV2 imageV2Datastore.DataStore,
	imageCVEs imageCVEDataStore.DataStore,
	sensorConnMgr connection.Manager,
	reprocessor reprocessor.Loop,
	imagecveView views.CveView,
) Manager {
	return &managerImpl{
		deployments:         deployments,
		images:              images,
		imagesV2:            imagesV2,
		imageCVEs:           imageCVEs,
		imageCVEView:        imagecveView,
		vulnReqs:            vulnReqs,
		connManager:         sensorConnMgr,
		reprocessor:         reprocessor,
		pendingReqCache:     pendingVulnReqsCache,
		activeReqCache:      activeVulnReqsCache,
		lastKnownSeqNumInfo: &monthSeqNumPair{},

		revertTimedDeferralsTickerDuration:      env.VulnDeferralTimedReObserveInterval.DurationSetting(),
		revertFixableCVEDeferralsTickerDuration: env.VulnDeferralFixableReObserveInterval.DurationSetting(),
		stopper:                                 concurrency.NewStopper(),

		upsertSem: semaphore.NewWeighted(1),
	}
}
